package com.lz.ccjdemo.utils.file.down;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;

import com.lz.ccjdemo.utils.file.callback.IProgressListener;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.lang.reflect.Array;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;

public class DownUtils {
    String mFilePath;
    String mUrl;
    String mFileName;
    boolean isPauseRunning = false;
    boolean isRunning = false;
    Long mOriginPosition = 0L;
    boolean isCancel = false;
    File mFile = null;
    ThreadPoolExecutor mThreadPoolExecutor;
    IProgressListener mIProgressListener;

    Long CONNECT_TIMEOUT = 60L;

    public DownUtils(String url, String filePath, String fileName) {
        mUrl = url;
        mFilePath = filePath;
        mFileName = fileName;
        mFile = new File(mFilePath);
        init();
    }

    private void init() {
        mOriginPosition = 0L;

        if (TextUtils.isEmpty(mUrl)) {
            throw new NullPointerException("error url=" + mUrl);
        }

        //判断文件路径是否存在  不存在创建目录
        if (!mFile.exists()) {
            mFile.mkdirs();
        }
        mThreadPoolExecutor = new ThreadPoolExecutor(1, 1, 5, TimeUnit.MINUTES, new LinkedBlockingDeque<Runnable>());
    }

    private void request() {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                .build();
        Request request = new Request.Builder().addHeader("RANGE", "bytes=$mOriginPosition-")
                .addHeader("Accept-Encoding", "identity")//避免服务端压缩大小 导致获取不到真实长度
                .url(mUrl).build();
        Response response = null;
        try {
            response = client.newCall(request).execute();
            ResponseBody body = response.body();
            isRunning = true;
            InputStream inputStream = body.byteStream();
            File pathResult = new File(mFile.getAbsolutePath(), mFileName);
            if (pathResult.exists()) {
                pathResult.delete();
            }
            if (body.contentLength() < 0) {
                onError(new Exception("下载失败"));
                return;
            }
            if (pathResult.exists() && pathResult.length() == body.contentLength()) {//如果文件已存在 直接完成下载
                onSuccess(pathResult.getAbsolutePath());
                return;
            }
            RandomAccessFile saveFile = new RandomAccessFile(pathResult, "rw");
            saveFile.seek(mOriginPosition);//移动到指定位置
            byte[] b = new byte[2048];//每次读取的长度设定
            long total = body.contentLength() + mOriginPosition;//断点续传时 避免总长度出现误差
            int len = inputStream.read(b);//第一次读取数据
            Long progress = mOriginPosition;//当前进度值
            while (len != -1 && !isPauseRunning) {
                progress += len;
                saveFile.write(b, 0, len);

                long[] array = {progress, total};
                Message msg = new Message();
                msg.what = 1;
                msg.obj = array;
                mHandler.sendMessage(msg);

                if (progress == total) {
                    onSuccess(pathResult.getAbsolutePath());
                }
                mOriginPosition = progress;
                len = inputStream.read(b);
            }
        } catch (Exception e) {
            e.printStackTrace();
            onError(e);
        } finally {
            isRunning = false;
        }
    }

    private void onError(Exception e) {
        Message msg = new Message();
        msg.what = 3;
        msg.obj = e;
        mHandler.sendMessage(msg);
        mFile.delete();
        isRunning = false;
        isPauseRunning = true;
    }

    private void onSuccess(String path) {
        Message msg = new Message();
        msg.what = 2;
        msg.obj = path;
        mHandler.sendMessage(msg);
    }

    private Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1:
                    if (mIProgressListener != null) {
                        if (msg.obj instanceof long[]) {
                            long[] result = (long[]) msg.obj;
                            mIProgressListener.onProgress(result[0], result[1]);
                        }
                    }
                    break;
                case 2:
                    if (mIProgressListener != null) {
                        if (msg.obj instanceof String) {
                            mIProgressListener.onSuccess((String) msg.obj);
                        } else {
                            mIProgressListener.onError(new Exception("下载失败"));
                        }
                    }
                    break;
                case 3:
                    if (mIProgressListener != null) {
                        if (msg.obj instanceof Exception) {
                            mIProgressListener.onError((Exception) msg.obj);
                        } else {
                            mIProgressListener.onError(new Exception("下载失败"));
                        }
                    }
                    break;
            }
        }
    };

    /**
     * 开始下载
     */
    public void startDown(long originPosition) {
        mOriginPosition = originPosition;
        isPauseRunning = false;
        mThreadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    request();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 继续未下载完的数据 进行下载
     */
    public void continueDown() {
        startDown(mOriginPosition);
    }

    public DownUtils registerProgressListener(IProgressListener progressListener) {
        mIProgressListener = progressListener;
        return this;
    }

    /**
     * 返回当前下载状态
     */
    public boolean isRunning() {
        return isRunning;
    }

    /**
     * 暂停下载
     */
    public void stopDown() {
        isPauseRunning = true;
    }

    /**
     * 取消下载
     */
    public void cancelDown() {
        stopDown();
        isCancel = true;
        mOriginPosition = 0L;
        mIProgressListener = null;
        //删除已下载文件
        File pathResult = new File(mFile.getAbsolutePath(), mFileName);
        if (pathResult.exists()) {
            pathResult.delete();
        }
    }
}
